package com.quick.springbootquicky.controller;

import com.quick.springbootquicky.pojo.TestUser;
import com.quick.springbootquicky.service.TestUserService;
import com.quick.springbootquicky.utils.*;
import jakarta.validation.constraints.Pattern;
import org.apache.ibatis.annotations.Delete;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/user")
public class TestUserController {

    @Autowired
    public TestUserService testUserService;


   /**Validation 对接口参数进行校验
		1、引入spring validation依赖
		2、在参数面前添加@Pattern注解,用正则表达式校验
		3、在controller类上添加@Validated注解
	*/
    /**
     * 注册账号
     * @param username wangzhang  lihaiyue
     * @param password 123abc456ef
     * @return
     */
    /**
     分开来注释一下：要求：由数字和字母组成，并且要同时含有数字和字母，且长度要在8-16位之间。
     ^ 匹配一行的开头位置
     (?![0-9]+$) 预测该位置后面不全是数字
     (?![a-zA-Z]+$) 预测该位置后面不全是字母
     [0-9A-Za-z] {8,16} 由8-16位数字或这字母组成
     $ 匹配行结尾位置注：(?!xxxx) 是正则表达式的负向零宽断言一种形式，标识预该位置后不是xxxx字符。
     */
    @PostMapping("/register")
    public Result<String> register(@Pattern(regexp = "^\\S{8,16}$")String username,
                                   @Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$")String password){
        TestUser user = testUserService.findByUserName(username);
        if(null ==user){
            testUserService.add(username,password);
            return  Result.success("注册成功");
        }else{
           return Result.error("该用户名已经注册");
        }
    }

    @RequestMapping("/test")
    public Result<String>test(){
        return Result.success("测试前端请求");
    }

    /**
     * 登入 ，登录成功后生成token，保存当前登录者的id 用户名，
     * 并每次在拦截器中，存储到当前用户线程中，用完再在拦截其中销毁
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/login")
    public Result<String> login(@RequestParam @Pattern(regexp = "^\\S{8,16}$")String username,
                                @RequestParam @Pattern(regexp = "^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{8,16}$")String password){
        TestUser user = testUserService.findByUserName(username);
        if(null !=user){
            String pmd5 = MD5Util.encryptMD5(password);
            if(pmd5.equals(user.getPassword())){
                Map<String,Object> claims = new HashMap<>();
                claims.put("id",user.getId());
                claims.put("username",user.getUsername());
                String token = JWTUtil.genToken(claims);
                //保存token到redis 以作校验,以用户名+id作为key
                RedisUtil.set(username+user.getId(),token);
                return  Result.success("登入成功",token);
            }else{
                return Result.error("密码错误");
            }

        }else{
            return Result.error("用户名错误");
        }
    }

    /**
     * 查询用户信息
     * @param token
     * @return
     */
    @GetMapping("/userInfo")
    public Result<TestUser> userInfo(@RequestHeader("Authorization")String token){
        //Map<String,Object> map = JWTUtil.parseToken(token);
        Map<String,Object> map = ThreadLocalUtil.get();//从当前线程中获取,在拦截器中清除
        String username = (String) map.get("username");
        TestUser user = testUserService.findByUserName(username);
        //ThreadLocalUtil.remove();//清除内存
        return Result.success("查询成功",user);
    }

    /**
     * 更新用户信息
     * @param user  @Validated在方法中添加这个注解，同时实体类中每个字段都加对应的注解，用于校验参数
     * @return
     */
    @PostMapping("/update")
    public Result<String> updateUser(@RequestBody @Validated TestUser user){
        testUserService.updateUser(user);
        return Result.success("更新成功",null);

    }

    /**
     * 更新头像
     * @param avatarUrl  @URL检验参数合法性
     * @return
     */
    @PatchMapping("/updateAvatar")
    public Result<String> updateAvatar(@RequestParam @URL String avatarUrl){
        testUserService.updateAvatar(avatarUrl);
        return Result.success("更新成功",null);

    }

    /**
     * 更新密码，更新成功后清除redis中的token，需要重新登录
     * @param params
     * @return
     */
    @PostMapping("/updatePwd")
    public Result updatePwd(@RequestBody Map<String,String>params,@RequestHeader("Authorization")String token){

        String oldPwd = params.get("old_pwd");
        String newPwd = params.get("new_pwd");
        String rePwd = params.get("re_pwd");

        if(!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd) ){
            return Result.error("参数有误");
        }
        if(!newPwd.equals(rePwd)){
            return Result.error("两次填写密码不一致");
        }
        Map<String,Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        TestUser user  = testUserService.findByUserName(username);
        if(!user.getPassword().equals(MD5Util.encryptMD5(oldPwd))){
            return Result.error("密码不正确");
        }


        testUserService.updatePwd(MD5Util.encryptMD5(newPwd));
        //修改密码后要删除以前的token，防止修改密码后直接请求其他接口，强迫重新登入
        RedisUtil.delete(username+user.getId());
        return Result.success("更新成功,请重新登录");

    }

    /**
     * 用户一般不允许删除
     * @param id
     * @return
     */
    @DeleteMapping("/delete")
    public Result<String> delete(Integer id){
        return Result.error("用户不允许删除");
    }


    /**
     * 退出
     * @return
     */
    @GetMapping("/logout")
    public Result<String> logout(){
        Map<String,Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        RedisUtil.delete(username+map.get("id"));
        ThreadLocalUtil.remove();
        return Result.success("退出成功");
    }




}
